package fem2.element;

import inf.text.ArrayFormat;
import math2.MathUtilities;

import org.junit.Test;

import fem2.AbstractPatchTestCrackElement;
import fem2.Constraint;
import fem2.Element;
import fem2.Face;
import fem2.MaterialModel;
import fem2.Mesh;
import fem2.MeshPart;
import fem2.Model;
import fem2.Node;
import fem2.analysis.Analysis;
import fem2.analysis.NonlinearStaticManualAnalysis;
import fem2.element.ConstantCrackElement;
import fem2.enu.EchoLevelType;
import fem2.enu.State;
import fem2.material.StVenantKirchhoffMM;
import fem2.material.cohesive_law.CohesiveLaw;
import fem2.observer.StressObserver;

public class ConstantCrackElementOneElementTest extends AbstractPatchTestCrackElement {

	@Override
	public MaterialModel createMaterial() {
		double E = 25850;
		double nu = 0.18;
		double t = 200;
		State ss = State.PLANE_STRESS;
		return new StVenantKirchhoffMM(E, nu, t, 0, ss);
	}

	@Override
	public Element createElement(MeshPart mp, MaterialModel mm, CohesiveLaw cl) {
		double H = -1;
		double ft = 0.91;
		double km = 0.0;
		return new ConstantCrackElement(mp, mm, H, km, ft);
	}

	public Mesh createMesh1() {
		Mesh mesh = new Mesh();

		Node n1 = mesh.addNode(new Node(0, 0));
		Node n2 = mesh.addNode(new Node(1, 0.5));
		Node n3 = mesh.addNode(new Node(0, 1));

		mesh.addFace(new Face(n1, n2, n3));

		Constraint c1 = new Constraint(false, false);
		Constraint c2 = new Constraint(false, true);

		n1.setConstraint(c1);
		n2.setConstraint(c2);
		n3.setConstraint(c1);

		mesh.setNumberOfFields(2);

		return mesh;
	}

	@Test
	public void test1() {
		Model m = createModel(createMesh1());

		Constraint c = m.getMesh().getNode(1).getConstraint();
		c.setValue(0, 0.0001);

		double[] lambda = MathUtilities.createLambdaArray(0, 0.1, 1.2);

		Analysis an = new NonlinearStaticManualAnalysis(m, lambda);
		an.getStrategy().addObserver(new StressObserver(m));
		an.getStrategy().setEchoLevel(EchoLevelType.DEBUG);
		an.getStrategy().setEchoLevel(EchoLevelType.OUTPUT);
		an.run();

		for (int i = 0; i < 3; i++) {
			double[] uHatLocal = m.getMesh().getNode(i).getUHatLocal();
			System.out.println(ArrayFormat.format(uHatLocal));
			// Assert.assertEquals(Uh[i][0], uHatLocal[0], 1e-10);
			// Assert.assertEquals(Uh[i][1], uHatLocal[1], 1e-10);
		}
	}

	public Mesh createMesh2() {
		Mesh mesh = new Mesh();

		Node n1 = mesh.addNode(new Node(0, 0));
		Node n2 = mesh.addNode(new Node(1, 0));
		Node n3 = mesh.addNode(new Node(0.5, 1));

		mesh.addFace(new Face(n1, n2, n3));

		Constraint c1 = new Constraint(false, false);
		Constraint c2 = new Constraint(true, false);

		n1.setConstraint(c1);
		n2.setConstraint(c1);
		n3.setConstraint(c2);

		mesh.setNumberOfFields(2);

		return mesh;
	}

	@Test
	public void test2() {
		Model m = createModel(createMesh2());

		Constraint c = m.getMesh().getNode(2).getConstraint();
		c.setValue(1, 0.0001);

		double[] lambda = MathUtilities.createLambdaArray(0, 0.1, 1.2);

		Analysis an = new NonlinearStaticManualAnalysis(m, lambda);
		an.getStrategy().addObserver(new StressObserver(m));
		an.getStrategy().setEchoLevel(EchoLevelType.DEBUG);
		an.getStrategy().setEchoLevel(EchoLevelType.OUTPUT);
		an.run();

		for (int i = 0; i < 3; i++) {
			double[] uHatLocal = m.getMesh().getNode(i).getUHatLocal();
			System.out.println(ArrayFormat.format(uHatLocal));
			// Assert.assertEquals(Uh[i][0], uHatLocal[0], 1e-10);
			// Assert.assertEquals(Uh[i][1], uHatLocal[1], 1e-10);
		}
	}
}
